#include "srtsubtitle.h"

#include "Common/stringoperations.h"
#include "Common/fileoperations.h"

#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

bool operator<(const uint64 timestamp, const SubtitleEntity& entry)
{
    return timestamp < entry.startTime;
}

bool operator<(const SubtitleEntity& entry, const uint64 timestamp)
{
    return entry.endTime < timestamp;
}

SrtSubtitle::SrtSubtitle()
{
}

SrtSubtitle::SrtSubtitle(const string& filename)
{
    open(filename);
}

SrtSubtitle::~SrtSubtitle()
{
}

bool SrtSubtitle::getSubtitle(uint64 timestamp, SubtitleEntity& entity)
{
    SubtitleList::iterator iter = lower_bound(m_Subtitles.begin(), m_Subtitles.end(), timestamp);
    if (iter != m_Subtitles.end() && *iter == timestamp)
    {
        entity = *iter;
        return true;
    }

    return false;
}

void SrtSubtitle::open(const string& filename)
{
    m_Subtitles.clear();
    vector<string> subLines;
    readSubtitleFile(filename, subLines);

    int i = 0;
    while (static_cast<size_t>(i + 4) <= subLines.size())
    {
        SubtitleEntity entity;
        parseIndexLine(subLines[i++], entity);
        parseTimestampLine(subLines[i++], entity);
        parseFirstSubtitleLine(subLines[i++], entity);
        parseSecondSubtitleLine(subLines[i++], entity);
        m_Subtitles.push_back(entity);

        if (!entity.line2.empty())
        {
            ++i;
        }
    }
}

void SrtSubtitle::readSubtitleFile(const string& filename, vector<string>& lines)
{
    string buffer;
    if (!FileOperations::readTextFile(buffer, filename))
    {
        throw SubtitleException(string("Subtitle could not be opened: ") + filename);
    }

    StringOperations::dos2unix(buffer);
    StringOperations::tokenize(buffer, "\n", lines);
}

void SrtSubtitle::parseIndexLine(const string& line, SubtitleEntity& entity)
{
    throwOnEmpty(line);
    StringOperations::toNumeric(line, entity.index);
}

void SrtSubtitle::parseTimestampLine(const string& line, SubtitleEntity& entity)
{
    throwOnEmpty(line);

    int h1, h2, m1, m2, s1, s2, ms1, ms2;
    sscanf(line.c_str(), "%d:%d:%d,%d --> %d:%d:%d,%d", &h1, &m1, &s1, &ms1, &h2, &m2, &s2, &ms2);

    entity.startTime = h1*3600000 + m1*60000 + s1*1000 + ms1;
    entity.endTime   = h2*3600000 + m2*60000 + s2*1000 + ms2;
}

void SrtSubtitle::parseFirstSubtitleLine(const string& line, SubtitleEntity& entity)
{
    throwOnEmpty(line);
    entity.line1 = line;
}

void SrtSubtitle::parseSecondSubtitleLine(const string& line, SubtitleEntity& entity)
{
    entity.line2 = line;
}

void SrtSubtitle::throwOnEmpty(const std::string& line)
{
    if (line.empty())
    {
        throw SubtitleException("Invalid empty line in subtitle");
    }
}
